/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jsibbold.zoomage.example;

import com.lijiankun24.shadowlayout.AttrUtil;
import com.lijiankun24.shadowlayout.NumberUtil;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Component.DrawTask;
import ohos.agp.components.Component.EstimateSizeListener;
import ohos.agp.render.Canvas;
import ohos.agp.render.LinearShader;
import ohos.agp.render.MaskFilter;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.render.MaskFilter.Blur;
import ohos.agp.render.Paint.Join;
import ohos.agp.render.Paint.ShaderType;
import ohos.agp.render.Paint.StrokeCap;
import ohos.agp.render.Paint.Style;
import ohos.agp.render.Shader.TileMode;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * 自定义控件阴影
 *
 * @since 2021-06-04
 */
public class ShadowLayout extends DirectionalLayout implements EstimateSizeListener, DrawTask {
    private static final int ALL = 4369;
    private static final int TOP = 16;
    private static final int RIGHT = 256;
    private static final int BOTTOM = 4096;
    private static final int SIZEWITHMODE = 1073741824;
    private static final float START = 0.1F;
    private static final float STOP = 0.5F;
    private int mShadowColor;
    private float mShadowRadius;
    private float mShadowDx;
    private float mShadowDy;
    private int mShadowSide;
    private final Paint mShadowPaint;
    private final Paint mHelpPaint;
    private final Path path;

    /**
     * 构造方法
     *
     * @param var1 上下文
     */
    public ShadowLayout(Context var1) {
        this(var1, (AttrSet)null);
    }

    /**
     * 构造方法
     *
     * @param var1 上下文
     * @param var2 AttrSet
     */
    public ShadowLayout(Context var1, AttrSet var2) {
        this(var1, var2, (String)null);
    }

    /**
     * 构造方法
     *
     * @param var1 上下文
     * @param var2 AttrSet
     * @param var3 var3
     */
    public ShadowLayout(Context var1, AttrSet var2, String var3) {
        super(var1, var2, var3);
        this.mShadowRadius = 0.0F;
        this.mShadowDx = 0.0F;
        this.mShadowDy = 0.0F;
        this.mShadowSide = ALL;
        this.mShadowPaint = new Paint();
        this.mHelpPaint = new Paint();
        this.mShadowPaint.setDither(true);
        this.mShadowPaint.setAntiAlias(true);
        this.path = new Path();
        this.initialize(var2);
        this.setEstimateSizeListener(this);
        this.addDrawTask(this);
    }

    private void initialize(AttrSet var1) {
        this.mShadowRadius = AttrUtil.getFloatValue(var1, "shadowRadius", 0.0F);
        this.mShadowColor = Color.getIntColor(AttrUtil.getStringValue(var1, "shadowColor", "#000000"));
        this.mShadowDx = AttrUtil.getFloatValue(var1, "shadowDx", 0.0F);
        this.mShadowDy = AttrUtil.getFloatValue(var1, "shadowDy", 0.0F);
        this.mShadowSide = AttrUtil.getIntegerValue(var1, "shadowSide", ALL);
        this.initPaint();
    }

    private void initPaint() {
        this.mHelpPaint.setColor(Color.TRANSPARENT);
        this.mHelpPaint.setStyle(Style.FILL_STYLE);
        this.mHelpPaint.setStrokeCap(StrokeCap.ROUND_CAP);
        this.mShadowPaint.setColor(new Color(this.mShadowColor));
        this.mShadowPaint.setStyle(Style.FILL_STYLE);
        this.mShadowPaint.setStrokeCap(StrokeCap.ROUND_CAP);
        this.mShadowPaint.setStrokeJoin(Join.ROUND_JOIN);
        this.mShadowPaint.setMaskFilter(new MaskFilter(this.mShadowRadius, Blur.OUTER));
    }

    /**
     * EstimateSize
     *
     * @param var1 var1
     * @param var2 var2
     * @return isBoolean
     */
    public boolean onEstimateSize(int var1, int var2) {
        float var3 = this.mShadowRadius;
        float var4 = 0.0F;
        float var5 = 0.0F;
        float var6 = (float) this.getEstimatedWidth();
        float var7 = (float) this.getEstimatedHeight();
        int var8 = 0;
        int var9 = 0;
        int var10 = 0;
        int var11 = 0;
        this.getWidth();
        if ((this.mShadowSide & 1) == 1) {
            var4 = -var3;
            var8 = (int) var3;
        }

        if ((this.mShadowSide & TOP) == TOP) {
            var5 = -var3;
            var9 = (int) var3;
        }

        if ((this.mShadowSide & RIGHT) == RIGHT) {
            var6 = (float) NumberUtil.add(this.getEstimatedWidth(), var3);
            var10 = (int) var3;
        }

        if ((this.mShadowSide & BOTTOM) == BOTTOM) {
            var7 = (float) NumberUtil.add(this.getEstimatedHeight(), var3);
            var11 = (int) var3;
        }

        if (String.valueOf(this.mShadowDy) != null) {
            var7 = (float) NumberUtil.add(var7, this.mShadowDy);
            var11 += (int) this.mShadowDy;
        }

        if (String.valueOf(this.mShadowDx) != null) {
            var6 = (float) NumberUtil.add(var6, this.mShadowDx);
            var10 += (int) this.mShadowDx;
        }

        EstimateSpec.getSizeWithMode(EstimateSpec.getSize((int) NumberUtil.
            sub(var6, var4)), SIZEWITHMODE);
        EstimateSpec.getSizeWithMode(EstimateSpec.getSize((int) NumberUtil.
            sub(var7, var5)), SIZEWITHMODE);
        this.setPadding(var8, var9, var10, var11);
        return false;
    }

    /**
     * 设置阴影颜色
     *
     * @param var1 颜色
     */
    public void setShadowColor(int var1) {
        this.mShadowColor = var1;
        this.initPaint();
        this.postLayout();
        this.invalidate();
    }

    /**
     * 设置阴影半径
     *
     * @param var1 半径
     */
    public void setShadowRadius(float var1) {
        this.mShadowRadius = var1;
        this.postLayout();
        this.invalidate();
    }

    /**
     * onDraw
     *
     * @param var1 Component
     * @param var2 Canvas
     */
    public void onDraw(Component var1, Canvas var2) {
        int left = var1.getLeft();
        int top = var1.getTop();
        int right = var1.getRight();
        int bottom = var1.getBottom();
        double var3 = NumberUtil.sub(NumberUtil.add(left, this.mShadowRadius), this.mShadowDx);
        double var5 = NumberUtil.sub(NumberUtil.add(top, this.mShadowRadius), this.mShadowDy);
        double var7 = NumberUtil.sub(NumberUtil.sub(right, this.mShadowRadius), this.mShadowDx);
        double var9 = NumberUtil.sub(NumberUtil.sub(bottom, this.mShadowRadius), this.mShadowDy);
        RectFloat mRectFloat = new RectFloat((float) var3, (float) var5, (float) var7, (float) var9);
        Point[] newPoints = this.getBoundPoint(mRectFloat);
        float[] newStops = new float[]{START, STOP};
        Color[] colors = new Color[]{new Color(this.mShadowColor), Color.TRANSPARENT};
        LinearShader var11 = new LinearShader(newPoints, newStops, colors, TileMode.CLAMP_TILEMODE);
        this.mShadowPaint.setShader(var11, ShaderType.LINEAR_SHADER);
        this.mShadowPaint.setStrokeWidth(this.mShadowRadius);
        this.path.lineTo(this.mShadowRadius, this.mShadowRadius);
        this.path.lineTo(this.mShadowRadius, (float) NumberUtil.add(mRectFloat.getHeight(), this.mShadowRadius));
        this.path.lineTo((float) NumberUtil.add(mRectFloat.getWidth(), this.mShadowRadius),
            (float) NumberUtil.add(mRectFloat.getHeight(), this.mShadowRadius));
        this.path.lineTo((float) NumberUtil.add(mRectFloat.getWidth(), this.mShadowRadius), this.mShadowRadius);
        this.path.lineTo(this.mShadowRadius, this.mShadowRadius);
        this.path.close();
        var2.drawRect(mRectFloat, this.mHelpPaint);
        var2.drawPath(this.path, this.mShadowPaint);
    }

    /**
     * setAlpha
     *
     * @param var1 var1
     */
    public void setAlpha(float var1) {
        super.setAlpha(var1);
        this.mShadowPaint.setAlpha(var1);
    }

    private Point[] getBoundPoint(RectFloat var1) {
        Point var2 = new Point(var1.left, var1.top);
        Point var3 = new Point(var1.left, var1.bottom);
        Point var4 = new Point(var1.right, var1.bottom);
        Point var5 = new Point(var1.right, var1.top);
        return new Point[]{var2, var3, var4, var5};
    }
}
